package HostComm;

//UI package
import UserInterface.Host_View;
//imports used by Host
import javax.comm.CommPortIdentifier;
import javax.comm.CommDriver;
import java.util.Enumeration;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;

/**
 * 
 * @author Dakota Brown, Travis Shuff
 * 
 * Host: 
 * 1.) Creates the database tables: Host_to_Applet, Applet_to_Host, and Queue
 * 2.) Initializes COMM Ports
 * 3.) Recognizes Robots on their respective COMM ports and creates a thread for each
 * 4.) Creates a Queue thread to keep Clients on a waiting list with position 1 being 
 *     being the current user of the CRIEP system
 * 
 * @since 10/18/11
 */
public class Host {

    private HashMap<String, CommPortIdentifier> cpiMap = new HashMap<String, CommPortIdentifier>();
    protected static ArrayList<Robot> robotList = new ArrayList<Robot>();
    static int robotCount = 1;
    public QueueHost queueHost;
    //ConnectObject for storing connection settings
    public HostConnectionObject connObj = new HostConnectionObject("xenoserver.dnsalias.com/crieplite",
            "Dakota", "password", "22");
    
    //Needs reference to view to display output
    private Host_View view;

    /**
     * Constructor: Default Constructor
     * 
     * @since 10/18/11
     */
    public Host(Host_View view_In) {
        view = view_In;
    }

    /**
     * 
     * @param conObj
     * 
     * @return 
     * 
     * @since 10/18/11
     */
    public String connect(HostConnectionObject conObj) {
        return HostDBComm.connect(conObj);
    }

    /**
     * 
     * @return true if connected, false if not connected
     * 
     * @since 10/18/11
     */
    public boolean isConnected() {
        return HostDBComm.isConnected();
    } 
    
    
    
    /*
     * Stops all Robot Threads, clears database, and closes the database connection
     * 
     * @since 09/30/11
     */
    public void closeHost() {
        for (int i = 0; i < robotList.size(); i++) {
            robotList.get(i).stop();
        }
        HostDBComm.disconnect();
        System.exit(0);
    }

    /**
     * Using the Java Communications API, a HashMap<String, CommPortIdentifier> 
     * is filled with all COMM ports and their identifier
     * 
     * @since 10/11/11
     */
    public String initCommPorts() {
        try {
            CommDriver commDriver = (CommDriver) Class.forName("com.sun.comm.Win32Driver").newInstance();
            commDriver.initialize();
            Enumeration pList = CommPortIdentifier.getPortIdentifiers();

            while (pList.hasMoreElements()) {
                CommPortIdentifier cpi = (CommPortIdentifier) pList.nextElement();
                String name = cpi.getName();
                if (name.startsWith("COM") && !cpiMap.containsKey(name)) {
                    cpiMap.put(name, cpi);
                }
            }
            return "Comm Ports Initialized";
        } catch (Exception ex) {
            return ex.toString();
        }
    }

    /**
     * Uses COMM port to check if a Robot is connected to them and adds to
     * an ArrayList<Robot> robotList if a new Robot is created
     * 
     * @return "Connected Using"  if Robot is created or 
     *         "Error: " otherwise
     * 
     * @since 10/11/11
     */
    public String findRobot(CommPortIdentifier c) {
        CommPortIdentifier cpi = c;
        try {
            robotList.add(createRobot("Robot" + robotCount, new RobotComm("RobotComm" + robotCount, cpi), robotCount++));
            return "Connected Using ";
        } catch (Exception ex) {
            return "Error: ";

        }
    }

    /**
     *
     * Constructs a Robot by defining it's parameters
     * 
     * @param robotID The name of the Robot
     * @param robotComm The connection between the HostDBComm and the physical Robots
     * @param robotCount counter used to identify the Robot's beginning location based on number
     * @return Robot with completed information
     * 
     * @since 10/11/11
     */
    public Robot createRobot(String robotID, RobotComm robotComm, int robotCount) {
        char initHeading = '\0';
        Point initPoint = null;
        int[] path = null;
        switch (robotCount) {
            case 1:
                initHeading = 'N';
                initPoint = new Point(0, 0);
                path = new int[]{0, 1, 1};
                break;
            case 2:
                initHeading = 'E';
                initPoint = new Point(0, 5);
                path = new int[]{0, 1, 1};
                break;
            case 3:
                initHeading = 'S';
                initPoint = new Point(5, 5);
                path = new int[]{0, 1, 1};
                break;
            case 4:
                initHeading = 'W';
                initPoint = new Point(5, 0);
                path = new int[]{0, 1, 1};
                break;
        }
        return new Robot(robotID, robotComm, initHeading, initPoint, path);
    }

    /**
     * Sends physical robot it's information, allows the Robot to
     * access the database and store the robot's info in the Host_to_Applet table,
     * then starts its Thread
     * 
     * @since 09/30/11
     */
    public void init() {
        for (int i = 0; i < robotList.size(); i++) {
            robotList.get(i).initRobot();
            robotList.get(i).initDB();
            new Thread(robotList.get(i)).start();
        }
    }

    /**
     * 
     * @return an iterator for cpiMap
     * 
     * @since 10/11/11
     */
    public Iterator getCommIterator() {
        return cpiMap.keySet().iterator();
    }

    /**
     * 
     * @return cpiMap (use after cpiMap is filled)
     * 
     * @since 10/11/11
     */
    public HashMap<String, CommPortIdentifier> useCPIMap() {
        return cpiMap;
    }

    /**
     * 
     * @return robotList.size()
     * 
     * @since 10/11/11
     */
    public int getNumOfRobots() {
        return robotList.size();
    }

    /**
     * 
     * @return true if robotList has Robots in it
     *         or false otherwise
     */
    public boolean robotsCreated() {
        if (!robotList.isEmpty()) {
            return true;
        } else {
            return false;
        }
    }
    
    
    /**
     * removes ActionListener from JMenuItem connect, Begins QueueHost Thread,
     * initializes COMM Ports, and starts Robot Threads where there are 
     * Robots are connected
     * 
     * @since 10/18/11
     */
    
    public void startUp() {
        //disable connect option
        //connect.removeActionListener(connect.getActionListeners()[0]);
        queueHost = new QueueHost();
        new Thread(queueHost).start();

        view.displayStatus(initCommPorts());

        view.displayStatus("Finding Robots");
        Iterator iter = getCommIterator();
        while (iter.hasNext()) {
            CommPortIdentifier c = useCPIMap().get(iter.next());
            String name = c.getName();
            view.displayStatus("Searching " + name + "...");
            view.displayStatus(findRobot(c) + name);
        }

        view.setRobotCount(getNumOfRobots());
        view.displayStatus("Search Complete");

        if (robotsCreated()) {
            //creates Thread for each robot
            init();
        }
    }
    
    
}
